package com.gupao.javavip.rpc.framework.client;

import com.gupao.javavip.rpc.framework.protocol.RPCRequest;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

@Component
@CommonsLog
public class RPCInvoke {
    @Autowired
    private RPCClientConfig config;

    @Autowired
    private ZKDiscovery zkDiscovery;

    public void setConfig(RPCClientConfig config) {
        this.config = config;
    }

    public void setZkDiscovery(ZKDiscovery zkDiscovery) {
        this.zkDiscovery = zkDiscovery;
    }

    public Object send(RPCRequest request) {
        if (config == null || config.getPort() <= 0 || StringUtils.isEmpty(config.getHost())) {
            throw new RuntimeException("需配置服务端地址和端口！");
        }

        if (request == null) {
            throw new RuntimeException("需指定请求的服务！");
        }

        ServiceNode serviceNode = zkDiscovery.discovery(config.getServiceId());
        log.debug("请求发送至：" + serviceNode);

        Socket socket = null;
        Object result = null;
        ObjectOutputStream outputStream = null;
        ObjectInputStream inputStream = null;

        try {
            socket = new Socket(serviceNode.getHost(), serviceNode.getPort()); //建立连接

            outputStream = new ObjectOutputStream(socket.getOutputStream());//网络socket
            outputStream.writeObject(request); //序列化()
            outputStream.flush();

            inputStream = new ObjectInputStream(socket.getInputStream());
            result = inputStream.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
}
